home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / cdity / cgxdpms.lha / CGXDPMS.c < prev    next >
C/C++ Source or Header  |  1997-10-08  |  14KB  |  760 lines

  1. #include <clib/alib_protos.h>
  2. #include <cybergraphics/cybergraphics.h>
  3. #include <exec/execbase.h>
  4. #include <exec/memory.h>
  5. #include <intuition/intuitionbase.h>
  6. #include <proto/commodities.h>
  7. #include <proto/cybergraphics.h>
  8. #include <proto/dos.h>
  9. #include <proto/exec.h>
  10. #include <proto/intuition.h>
  11. #include <proto/icon.h>
  12. #include <workbench/startup.h>
  13. #include <string.h>
  14.  
  15.  
  16. /* Compiler specific stuff. */
  17. #define SAVEDS    __saveds
  18. #define ASM    __asm
  19. #define REG(x)    register __ ## x
  20. #define STKARGS    __stdargs
  21.  
  22. #define VERSION    "1.2"
  23. #define DATE    "9.10.97"
  24.  
  25.  
  26. /* ----- Global variables ------------------------------------------------- */
  27.  
  28.  
  29. struct Library        *CxBase;
  30. struct Library        *CyberGfxBase;
  31. struct DosLibrary    *DOSBase;
  32. struct Library        *IconBase;
  33. struct IntuitionBase    *IntuitionBase;
  34. struct ExecBase        *SysBase;
  35.  
  36. struct MsgPort        *CxPort;
  37. struct WBStartup    *WBMsg;
  38. CxObj            *Broker;
  39. CxObj            *Sender;
  40. CxObj            *Custom;
  41.  
  42. LONG    StandbyTime;
  43. LONG    SuspendTime;
  44. LONG    OffTime;
  45. LONG    IETime;
  46. LONG    StandbyCounter;
  47. LONG    SuspendCounter;
  48. LONG    OffCounter;
  49. LONG    SendShift;
  50. LONG    NoMouse;
  51. LONG    State;
  52. LONG    FinalState;
  53.  
  54. struct InputEvent    ShiftDown;
  55. struct InputEvent    ShiftUp;
  56.  
  57. TEXT    BlankKey[ 128 ];
  58.  
  59. #define DEF_CXPRI    1
  60. #define DEF_STANDBY    20
  61. #define DEF_SUSPEND    20
  62. #define DEF_OFF        20
  63. #define DEF_SENDSHIFT    1
  64.  
  65. #define ID_SENDER    1
  66. #define ID_CUSTOM    2
  67. #define ID_BLANK    3
  68.     /* Don't know if this is a good value for ie.dead... They key code
  69.      * should be for a non-existant key. Oh well, doesn't cause Enforcer
  70.      * hits for me at least. ;)
  71.      */
  72. #define MAGIC    ( APTR ) 81008100L
  73.  
  74. struct Args
  75. {
  76.     LONG    *CxPriority;
  77.     STRPTR    BlankKey;
  78.     LONG    *StandbyTime;
  79.     LONG    *SuspendTime;
  80.     LONG    *OffTime;
  81.     LONG    *ShiftTime;
  82.     LONG    SendShift;
  83.     LONG    NoMouse;
  84. };
  85.  
  86. #define TEMPLATE "CX_PRIORITY/K/N,BLANKKEY/K,STANDBYTIME/K/N,SUSPENDTIME/K/N,OFFTIME/K/N,SHIFTTIME/K/N,SENDSHIFT/S,NOMOUSE/S"
  87.  
  88.  
  89. /* ----- Startup code ----------------------------------------------------- */
  90.  
  91.  
  92. static LONG    Main( VOID );
  93.  
  94.  
  95. LONG SAVEDS
  96. Startup( VOID )
  97. {
  98.     LONG    r = 100;
  99.  
  100.     SysBase = *( ( struct ExecBase ** ) 4 );
  101.  
  102.     {
  103.         struct Process    *thisTask = ( struct Process * ) FindTask( NULL );
  104.  
  105.         if( !thisTask->pr_CLI )
  106.         {
  107.             /* Handle Workbench startup message */
  108.             struct MsgPort    *port = &thisTask->pr_MsgPort;
  109.  
  110.             WaitPort( port );
  111.             WBMsg = ( struct WBStartup * ) GetMsg( port );
  112.         }
  113.     }
  114.  
  115.     SetSignal( 0, SIGBREAKF_CTRL_C );
  116.  
  117.     if( SysBase->LibNode.lib_Version >= 37 )
  118.     {
  119.         r = Main();
  120.     }
  121.  
  122.     if( WBMsg )
  123.     {
  124.         Forbid();
  125.         ReplyMsg( ( struct Message * ) WBMsg );
  126.     }
  127.  
  128.     return( r );
  129. }
  130.  
  131.  
  132. struct NewBroker    NewBroker =
  133. {
  134.     NB_VERSION,
  135.     "CGXDPMS",
  136.     "CGXDPMS " VERSION " by Magnus Holmgren",
  137.     "DPMS manager for CyberGraphX",
  138.     NBU_UNIQUE, 0, 0,
  139.     NULL, 0
  140. };
  141.  
  142.  
  143. static const TEXT Ver[]    = "$VER: CGXDPMS " VERSION " (" DATE ")";
  144.  
  145.  
  146. /* ----- Misc ------------------------------------------------------------- */
  147.  
  148.  
  149. static LONG
  150. MyRequestA( STRPTR title, STRPTR body, STRPTR gads, APTR args )
  151. {
  152.     struct EasyStruct    es;
  153.  
  154.     es.es_StructSize = sizeof( es );
  155.     es.es_Flags = 0;
  156.     es.es_Title = title;
  157.     es.es_TextFormat = body;
  158.     es.es_GadgetFormat = gads;
  159.     return( EasyRequestArgs( NULL, &es, NULL, args ) );
  160. }
  161.  
  162.  
  163. static LONG
  164. MyRequest( STRPTR title, STRPTR body, STRPTR gads, ... )
  165. {
  166.     return( MyRequestA( title, body, gads, &gads + 1 ) );
  167. }
  168.  
  169.  
  170. static VOID
  171. ErrRequest( STRPTR body, ... )
  172. {
  173.     if( WBMsg )
  174.     {
  175.         MyRequestA( "CGXDPMS error message", body, "Quit", &body + 1 );
  176.     }
  177.     else
  178.     {
  179.         VPrintf( body, &body + 1 );
  180.         PutStr( "\n" );
  181.     }
  182. }
  183.  
  184.  
  185. /* ----- Libs ------------------------------------------------------------- */
  186.  
  187.  
  188. static struct Library *
  189. OpenLib( STRPTR name, LONG ver )
  190. {
  191.     struct Library    *lib;
  192.  
  193.     if( !( lib = OpenLibrary( name, ver ) ) )
  194.     {
  195.         ErrRequest( "Couldn't open %s\nversion %ld or higher!", name, ver );
  196.     }
  197.  
  198.     return( lib );
  199. }
  200.  
  201.  
  202. #define CloseLib(lib)    CloseLibrary( ( struct Library * ) lib )
  203.  
  204.  
  205. static VOID
  206. CloseLibs( VOID )
  207. {
  208.     if( DOSBase )
  209.     {
  210.         CloseLib( DOSBase );
  211.         CloseLib( IntuitionBase );
  212.         CloseLib( CyberGfxBase );
  213.         CloseLib( CxBase );
  214.     }
  215. }
  216.  
  217.  
  218. static LONG
  219. OpenLibs( VOID )
  220. {
  221.     LONG    rc = FALSE;
  222.  
  223.     if( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) )
  224.     {
  225.         if( IntuitionBase = ( struct IntuitionBase * ) OpenLibrary( "intuition.library", 37 ) )
  226.         {
  227.             if( ( CyberGfxBase = OpenLib( "cybergraphics.library", 40 ) )
  228.                 && ( CxBase = OpenLib( "commodities.library", 37 ) ) )
  229.             {
  230.                 rc = TRUE;
  231.             }
  232.         }
  233.     }
  234.  
  235.     return( rc );
  236. }
  237.  
  238.  
  239. /* ----- Argument parsing ------------------------------------------------- */
  240.  
  241.  
  242. static VOID
  243. GetBlankKey( STRPTR str )
  244. {
  245.     if( str )
  246.     {
  247.         strncpy( BlankKey, str, sizeof( BlankKey ) - 1 );
  248.     }
  249. }
  250.  
  251.  
  252. static LONG
  253. GetNumTT( struct DiskObject *icon, STRPTR name, LONG def )
  254. {
  255.     STRPTR    str;
  256.     LONG    val;
  257.  
  258.     val = def;
  259.  
  260.     if( str = FindToolType( ( UBYTE ** ) icon->do_ToolTypes, name ) )
  261.     {
  262.         if( StrToLong( str, &val ) == -1 )
  263.         {
  264.             MyRequest( "CGXDMPS Warning", "Argument for %s should be numeric.\nUsing default (%ld).", "OK", name, def );
  265.             val = def;
  266.         }
  267.     }
  268.  
  269.     return( val );
  270. }
  271.  
  272.  
  273. static LONG
  274. GetTimeTT( struct DiskObject *icon, STRPTR name, LONG def )
  275. {
  276.     /* return( SMult32( GetNumTT( icon, name, def ), 60 ) ); */
  277.     return( GetNumTT( icon, name, def ) * 60 );
  278. }
  279.  
  280.  
  281. static LONG
  282. ParseWBArgs( VOID )
  283. {
  284.     LONG    rc = FALSE;
  285.  
  286.     if( IconBase = OpenLib( "icon.library", 37 ) )
  287.     {
  288.         struct DiskObject    *icon;
  289.         BPTR    oldDir;
  290.  
  291.         oldDir = CurrentDir( WBMsg->sm_ArgList[ 0 ].wa_Lock );
  292.  
  293.         /* Lazy parsing: Ignore any multiselected icons... */
  294.         if( icon = GetDiskObject( WBMsg->sm_ArgList[ 0 ].wa_Name ) )
  295.         {
  296.             NewBroker.nb_Pri = GetNumTT( icon, "CX_PRIORITY", DEF_CXPRI );
  297.             GetBlankKey( FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "BLANKKEY" ) );
  298.             StandbyTime      = GetTimeTT( icon, "STANDBYTIME", DEF_STANDBY );
  299.             SuspendTime      = GetTimeTT( icon, "SUSPENDTIME", DEF_SUSPEND );
  300.             OffTime          = GetTimeTT( icon, "OFFTIME",     DEF_OFF );
  301.             IETime           = GetTimeTT( icon, "SHIFTTIME",   DEF_SENDSHIFT );
  302.             SendShift        = ( LONG ) FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "SENDSHIFT" );
  303.             NoMouse          = ( LONG ) FindToolType( ( UBYTE ** ) icon->do_ToolTypes, "NOMOUSE" );
  304.             rc = TRUE;
  305.  
  306.             FreeDiskObject( icon );
  307.         }
  308.         else
  309.         {
  310.             ErrRequest( "Couldn't get program icon!" );
  311.         }
  312.  
  313.         CurrentDir( oldDir );
  314.         CloseLibrary( IconBase );
  315.     }
  316.     else
  317.     {
  318.         ErrRequest( "Couldn't open icon.library\nversion 37 or higher!" );
  319.     }
  320.  
  321.     return( rc );
  322. }
  323.  
  324.  
  325. static LONG
  326. GetNum( LONG *val, LONG def )
  327. {
  328.     LONG    rc;
  329.  
  330.     rc = def;
  331.  
  332.     if( val )
  333.     {
  334.         rc = *val;
  335.     }
  336.  
  337.     return( rc );
  338. }
  339.  
  340.  
  341. static LONG
  342. GetTime( LONG *val, LONG def )
  343. {
  344.     /* return( SMult32( GetNum( val, def ), 60 ) ); */
  345.     return( GetNum( val, def ) * 60 );
  346. }
  347.  
  348.  
  349. /* SAS/C insists on using in an optimized memset (that also is quite large)
  350.  * when compiling for a 68020+. Not what we want here, since we only want
  351.  * to clear less than 100 bytes *once*. So we have our own simple one
  352.  * instead.
  353.  */
  354. static VOID
  355. ClrMem( UBYTE *buf, LONG size )
  356. {
  357.     do
  358.     {
  359.         *buf++ = 0;
  360.     }
  361.     while( --size );
  362. }
  363.  
  364.  
  365. static LONG
  366. ParseCLIArgs( VOID )
  367. {
  368.     struct Args    args;
  369.     struct RDArgs    *rdarg;
  370.     LONG    rc = FALSE;
  371.  
  372.     ClrMem( ( UBYTE * ) &args, sizeof( args ) );
  373.  
  374.     if( rdarg = ReadArgs( TEMPLATE, ( LONG * ) &args, NULL ) )
  375.     {
  376.         NewBroker.nb_Pri = GetNum( args.CxPriority,  DEF_CXPRI );
  377.         GetBlankKey( args.BlankKey );
  378.         StandbyTime      = GetTime( args.StandbyTime, DEF_STANDBY );
  379.         SuspendTime      = GetTime( args.SuspendTime, DEF_SUSPEND );
  380.         OffTime          = GetTime( args.OffTime,     DEF_OFF );
  381.         IETime           = GetTime( args.ShiftTime,   DEF_SENDSHIFT );
  382.         SendShift        = args.SendShift;
  383.         NoMouse          = args.NoMouse;
  384.         rc = TRUE;
  385.  
  386.         FreeArgs( rdarg );
  387.     }
  388.  
  389.     return( rc );
  390. }
  391.  
  392.  
  393. static LONG
  394. ParseArgs( VOID )
  395. {
  396.     return( ( LONG ) ( WBMsg ? ParseWBArgs() : ParseCLIArgs() ) );
  397. }
  398.  
  399.  
  400. /* ----- Commodity support ------------------------------------------------ */
  401.  
  402.  
  403. static VOID
  404. Unblank( CxMsg *msg )
  405. {
  406.     StandbyCounter = StandbyTime;
  407.     SuspendCounter = SuspendTime;
  408.     OffCounter     = OffTime;
  409.  
  410.     if( State != DPMS_ON )
  411.     {
  412.         State = DPMS_ON;
  413.         RouteCxMsg( msg, Sender );
  414.     }
  415. }
  416.  
  417.  
  418. /* This function runs on the input.device task context. Thus, we need to
  419.  * set smalldata base, make sure we don't call any nasty functions, and
  420.  * generally try to do our job quickly.
  421.  */
  422. static STKARGS VOID SAVEDS
  423. CxCustomFunc( register CxMsg *msg, CxObj *obj )
  424. {
  425.     struct InputEvent    *ie;
  426.     static LONG    LastSecs, LastIE;
  427.     LONG        diff;
  428.  
  429.     ie = ( struct InputEvent * ) CxMsgData( msg );
  430.  
  431.     switch( ie->ie_Class )
  432.     {
  433.         case IECLASS_RAWMOUSE:
  434.         case IECLASS_POINTERPOS:
  435.         case IECLASS_NEWPOINTERPOS:
  436.             /* Ignore mouse movements while blanked? */
  437.             if( !( NoMouse && ( State != DPMS_ON ) && ( ie->ie_Code == IECODE_NOBUTTON ) ) )
  438.             {
  439.                 Unblank( msg );
  440.             }
  441.  
  442.             break;
  443.  
  444.         case IECLASS_RAWKEY:
  445.             /* Ignore rawkeys we send out, as well as key releases
  446.              * (to make the hotkey possible).
  447.              */
  448.             if( !( ( ie->ie_position.ie_addr == MAGIC ) || ( ie->ie_Code & IECODE_UP_PREFIX ) ) )
  449.             {
  450.                 Unblank( msg );
  451.             }
  452.  
  453.             break;
  454.  
  455.         case IECLASS_DISKREMOVED:
  456.         case IECLASS_DISKINSERTED:
  457.             Unblank( msg );
  458.             break;
  459.  
  460.         case IECLASS_TIMER:
  461.             diff = ie->ie_TimeStamp.tv_secs - LastSecs;
  462.  
  463.             /* Check for blanking at most once per second, if needed */
  464.             if( ( diff > 0 ) && ( State != FinalState ) && LastSecs )
  465.             {
  466.                 if( ( State < DPMS_STANDBY ) && ( StandbyCounter > 0 ) )
  467.                 {
  468.                     StandbyCounter -= diff;
  469.  
  470.                     if( StandbyCounter <= 0 )
  471.                     {
  472.                         State = DPMS_STANDBY;
  473.                         RouteCxMsg( msg, Sender );
  474.                     }
  475.                 }
  476.                 else if( ( State < DPMS_SUSPEND ) && ( SuspendCounter > 0 ) )
  477.                 {
  478.                     SuspendCounter -= diff;
  479.  
  480.                     if( SuspendCounter <= 0 )
  481.                     {
  482.                         State = DPMS_SUSPEND;
  483.                         RouteCxMsg( msg, Sender );
  484.                     }
  485.                 }
  486.                 else if( ( State < DPMS_OFF ) && ( OffCounter > 0 ) )
  487.                 {
  488.                     OffCounter -= diff;
  489.  
  490.                     if( OffCounter <= 0 )
  491.                     {
  492.                         State = DPMS_OFF;
  493.                         RouteCxMsg( msg, Sender );
  494.                     }
  495.                 }
  496.  
  497.                 if( SendShift && ( State != DPMS_ON ) )
  498.                 {
  499.                     diff = ie->ie_TimeStamp.tv_secs - LastIE;
  500.  
  501.                     if( diff > IETime )
  502.                     {
  503.                         LastIE = ie->ie_TimeStamp.tv_secs;
  504.                         ShiftDown.ie_TimeStamp = ie->ie_TimeStamp;
  505.                         ShiftUp.ie_TimeStamp   = ie->ie_TimeStamp;
  506.  
  507.                         /* Hm.. Maybe this would be better to do on the
  508.                          * main process' context. Oh well, not called
  509.                          * often anyway. At most once per minute. ;)
  510.                          */
  511.                         AddIEvents( &ShiftDown );
  512.                     }
  513.                 }
  514.             }
  515.  
  516.             LastSecs = ie->ie_TimeStamp.tv_secs;
  517.             break;
  518.     }
  519. }
  520.  
  521.  
  522. static VOID
  523. FreeBroker( VOID )
  524. {
  525.     DeleteCxObjAll( Broker );
  526.     DeleteMsgPort( CxPort );
  527. }
  528.  
  529.  
  530. static LONG
  531. InitBroker( VOID )
  532. {
  533.     LONG    rc = FALSE;
  534.  
  535.     ShiftUp.ie_Class = ShiftDown.ie_Class = IECLASS_RAWKEY;
  536.     ShiftDown.ie_Code = 0x60,    /* Shift (Left, I think) */
  537.     ShiftUp.ie_Code = IECODE_UP_PREFIX | 0x60;
  538.     ShiftUp.ie_position.ie_addr = ShiftDown.ie_position.ie_addr = MAGIC;
  539.     ShiftDown.ie_NextEvent = &ShiftUp;
  540.  
  541.     StandbyCounter = StandbyTime;
  542.     SuspendCounter = SuspendTime;
  543.     OffCounter     = OffTime;
  544.     State          = DPMS_ON;
  545.  
  546.     if( StandbyTime )
  547.     {
  548.         FinalState = DPMS_STANDBY;
  549.     }
  550.  
  551.     if( SuspendTime )
  552.     {
  553.         FinalState = DPMS_SUSPEND;
  554.     }
  555.  
  556.     if( OffTime )
  557.     {
  558.         FinalState = DPMS_OFF;
  559.     }
  560.  
  561.     if( CxPort = NewBroker.nb_Port = CreateMsgPort() )
  562.     {
  563.         LONG    err;
  564.  
  565.         if( Broker = CxBroker( &NewBroker, &err ) )
  566.         {
  567.             if( *BlankKey )
  568.             {
  569.                 AttachCxObj( Broker, HotKey( BlankKey, CxPort, ID_BLANK ) );
  570.             }
  571.  
  572.             AttachCxObj( Broker, Custom = CxCustom( CxCustomFunc, ID_CUSTOM ) );
  573.             AttachCxObj( Custom, Sender = CxSender( CxPort, ID_SENDER ) );
  574.  
  575.             if( CxObjError( Broker ) == COERR_BADFILTER )
  576.             {
  577.                 ErrRequest( "Bad hotkey description for BLANKKEY!\n('%s')", BlankKey );
  578.             }
  579.             else if( CxObjError( Broker ) || CxObjError( Custom ) )
  580.             {
  581.                 ErrRequest( "Not enough memory for Commodities objects!" );
  582.             }
  583.             else
  584.             {
  585.                 rc = TRUE;
  586.             }
  587.         }
  588.         else if( err != CBERR_DUP )
  589.         {
  590.             ErrRequest( "Couldn't create broker!" );
  591.         }
  592.     }
  593.     else
  594.     {
  595.         ErrRequest( "Couldn't create message port!" );
  596.     }
  597.  
  598.     if( !rc )
  599.     {
  600.         FreeBroker();
  601.     }
  602.  
  603.     return( rc );
  604. }
  605.  
  606.  
  607. static VOID
  608. HandleDPMS( VOID )
  609. {
  610.     struct Screen    *wb;
  611.  
  612.     /* Configurable screen name? Maybe for a future version... */
  613.     if( wb = LockPubScreen( "Workbench" ) )
  614.     {
  615.         /* Passing args via globals isn't the best perhaps, but it works. ;) */
  616.         CVideoCtrlTags( &wb->ViewPort,
  617.             SETVC_DPMSLevel,    State,
  618.         TAG_DONE );
  619.  
  620.         UnlockPubScreen( NULL, wb );
  621.     }
  622. }
  623.  
  624.  
  625. static VOID
  626. HandleKey( VOID )
  627. {
  628.     if( State == DPMS_ON )
  629.     {
  630.         /* Maybe we should use Semaphores or something here to prevent
  631.          * any odd behaviour. Not that likely to happen though (I
  632.          * think ;), and even if it does happen, the effects are
  633.          * really minor (not going to the "right" state).
  634.          */
  635.         if( StandbyTime )
  636.         {
  637.             StandbyCounter = 1;
  638.         }
  639.         else if( SuspendTime )
  640.         {
  641.             SuspendCounter = 1;
  642.         }
  643.         else if( OffTime )
  644.         {
  645.             OffCounter = 1;
  646.         }
  647.     }
  648. }
  649.  
  650.  
  651. static LONG
  652. HandleCxPort( VOID )
  653. {
  654.     CxMsg    *msg;
  655.     LONG    run = TRUE;
  656.  
  657.     while( msg = ( CxMsg * ) GetMsg( CxPort ) )
  658.     {
  659.         LONG    id, type;
  660.  
  661.         id = CxMsgID( msg );
  662.         type = CxMsgType( msg );
  663.         ReplyMsg( ( struct Message * ) msg );
  664.  
  665.         switch( type )
  666.         {
  667.             case CXM_IEVENT:
  668.                 switch( id )
  669.                 {
  670.                     case ID_SENDER:
  671.                         HandleDPMS();
  672.                         break;
  673.  
  674.                     case ID_BLANK:
  675.                         HandleKey();
  676.                         break;
  677.                 }
  678.  
  679.                 break;
  680.  
  681.             case CXM_COMMAND:
  682.                 switch( id )
  683.                 {
  684.                     case CXCMD_DISABLE:
  685.                         ActivateCxObj( Broker, FALSE );
  686.                         break;
  687.  
  688.                     case CXCMD_ENABLE:
  689.                         ActivateCxObj( Broker, TRUE );
  690.                         break;
  691.  
  692.                     case CXCMD_KILL:
  693.                         run = FALSE;
  694.                         break;
  695.                 }
  696.  
  697.                 break;
  698.         }
  699.     }
  700.  
  701.     return( run );
  702. }
  703.  
  704.  
  705. /* ----- Main program ----------------------------------------------------- */
  706.  
  707.  
  708. static VOID
  709. MainLoop( VOID )
  710. {
  711.     LONG    cxMask = 1 << CxPort->mp_SigBit;
  712.  
  713.     ActivateCxObj( Broker, TRUE );
  714.  
  715.     for( ;; )
  716.     {
  717.         LONG    sigs;
  718.  
  719.         sigs = Wait( cxMask | SIGBREAKF_CTRL_C );
  720.  
  721.         if( sigs & cxMask )
  722.         {
  723.             if( !HandleCxPort() )
  724.             {
  725.                 break;
  726.             }
  727.         }
  728.  
  729.         if( sigs & SIGBREAKF_CTRL_C )
  730.         {
  731.             break;
  732.         }
  733.     }
  734. }
  735.  
  736.  
  737. static LONG
  738. Main( VOID )
  739. {
  740.     LONG    ret = RETURN_FAIL;
  741.  
  742.     if( OpenLibs() )
  743.     {
  744.         if( ParseArgs() )
  745.         {
  746.             if( InitBroker() )
  747.             {
  748.                 MainLoop();
  749.                 ret = RETURN_OK;
  750.  
  751.                 FreeBroker();
  752.             }
  753.         }
  754.  
  755.         CloseLibs();
  756.     }
  757.  
  758.     return( ret );
  759. }
  760.